package controllers.GestionDataHistorica;

import jxl.Sheet;
import jxl.Workbook;
import models.*;

import java.io.File;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * Created with IntelliJ IDEA.
 * User: Daniel
 * Date: 16/01/13
 * Time: 04:00 PM
 * To change this template use File | Settings | File Templates.
 */
public class GestorExcelRegistros {

    public List<ErrorRegistro> errores = new ArrayList<ErrorRegistro>();

    public void ExtraerRegistrosExcel(String nombreArchivo)
    {
        File archivoExcel = LeerArchivoExcel(nombreArchivo);
        List<Hidregistro> hidregistros = ExtraerRegistrosPagina(archivoExcel);

        //se debe verificar que no hay errores para poder guardar los registros
        if(errores.size() == 0)
        {
            GuardarRegistros(hidregistros);
        }
    }

    public File LeerArchivoExcel(String nombreArchivo)
    {
        //carga el archivo con el nombre indicado
        File archivoExcel =  new File(nombreArchivo);
        return archivoExcel;
    }

    public List<Hidregistro> ExtraerRegistrosPagina(File archivoExcel)
    {
        List<Hidregistro> hidregistros = new ArrayList<Hidregistro>();

        try{
            Workbook hojaTrabajo = Workbook.getWorkbook(archivoExcel);
            int numeroPagina = 0;
            Sheet pagina = hojaTrabajo.getSheet(numeroPagina);

            int numFilas = pagina.getRows();
            // Recorre cada fila de la hoja
            for (int fila = 1; fila < numFilas; fila++)
            {
                //se debe obtener el contenido de las filas del archivo
                String identificador = pagina.getCell(0, fila).getContents();
                String fechaRegistro = pagina.getCell(1, fila).getContents();
                String valorRegistro = pagina.getCell(2, fila).getContents();
                String puntoMonitoreo = pagina.getCell(3, fila).getContents();
                String tipoMedicion = pagina.getCell(4, fila).getContents();
                String tipoRegistro = pagina.getCell(5, fila).getContents();
                String metodoGeneracion = pagina.getCell(6, fila).getContents();

                //se verifica si el registro formado con los datos de las filas forman un registro correcto
                if(RegistroValido(fila, identificador, fechaRegistro, valorRegistro, puntoMonitoreo,
                               tipoMedicion, tipoRegistro, metodoGeneracion))
                {
                    //se creaa el registro con los datos validados
                    Hidregistro hidregistro = CrearRegistro(identificador, fechaRegistro, valorRegistro, puntoMonitoreo,
                                                            tipoMedicion, tipoRegistro, metodoGeneracion);

                    //si el registro no es nulo (id valido) entonces se añade un registro a la lista de registros
                    if(hidregistro != null)
                    {
                        hidregistros.add(hidregistro);
                    }
                    errores.remove(errores.size() - 1);
                }
                else
                {
                    errores.get(fila - 1).ImprmirErrores();
                }
            }

            hojaTrabajo.close();
        }
        catch(Exception e)
        {
            System.out.println("readExcel ->" + e);
        }
        return hidregistros;
    }

    public boolean RegistroValido(int numeroFila, String identificador, String fechaRegistro, String valorRegistro,
                               String puntoMonitoreo, String tipoMedicion, String tipoRegistro, String metodoGeneracion)
    {
        ErrorRegistro errorRegistro = new ErrorRegistro(numeroFila);
        errores.add(errorRegistro);

        boolean identificadorCorrecto = VerificarIdentificador(identificador);
        boolean fechaCorrecta = VerificarFechaRegistro(fechaRegistro);
        boolean valorCorrecto = VerificarValorRegistro(valorRegistro);
        boolean puntoMonitoreoCorrecto = VerificarPuntoMonitoreo(puntoMonitoreo);
        boolean tipoMedicionCorrecto = VerificarTipoMedicion(tipoMedicion);
        boolean tipoRegistroCorrecto = VerificarTipoRegistro(tipoRegistro);
        boolean metodoGeneracionCorrecto = VerificarMetodoGeneracion(metodoGeneracion);

        return identificadorCorrecto && fechaCorrecta && valorCorrecto && puntoMonitoreoCorrecto &&
                tipoMedicionCorrecto && tipoRegistroCorrecto && metodoGeneracionCorrecto;
    }

    public boolean VerificarIdentificador(String identificador)
    {
        if(!identificador.equals(""))
        {
            if(esNumericoEntero(identificador))
            {
                Hidregistro hidregistro = Hidregistro.findById(Integer.valueOf(identificador));

                if(hidregistro == null)
                {
                    errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_IDENTIFICADOR_NO_EXISTENTE);
                    return false;
                }
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_IDENTIFICADOR_NO_NUMERICO);
                return false;
            }
        }
        return true;
    }

    public boolean VerificarFechaRegistro(String fechaRegistro)
    {
        if(!fechaRegistro.equals(""))
        {
            if(esFecha(fechaRegistro))
            {
                return true;
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_FECHA_FORMATO);
                return false;
            }
        }
        errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_FECHA_VACIA);
        return false;
    }

    public boolean VerificarValorRegistro(String valorRegistro)
    {
        if(!valorRegistro.equals(""))
        {
            if(esNumericoDecimal(valorRegistro))
            {
                return true;
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_VALOR_NO_NUMERICO);
                return false;
            }
        }
        errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_VALOR_VACIO);
        return false;
    }

    public boolean VerificarPuntoMonitoreo(String puntoMonitoreo)
    {
        if(!puntoMonitoreo.equals(""))
        {
            if(existePuntoMonitoreo(puntoMonitoreo))
            {
                return true;
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_PUNTO_MONITOREO_NO_EXISTENTE);
                return false;
            }
        }
        errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_PUNTO_MONITOREO_VACIO);
        return false;
    }

    public boolean VerificarTipoMedicion(String tipoMedicion)
    {
        if(!tipoMedicion.equals(""))
        {
            if(existeTipoMedicion(tipoMedicion))
            {
                return true;
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_TIPO_MEDICION_NO_EXISTENTE);
                return false;
            }
        }
        errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_TIPO_MEDICION_VACIO);
        return false;
    }

    public boolean VerificarTipoRegistro(String tipoRegistro)
    {
        if(!tipoRegistro.equals(""))
        {
            if(existeTipoRegistro(tipoRegistro))
            {
                return true;
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_TIPO_REGISTRO_NO_EXISTENTE);
                return false;
            }
        }
        errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_TIPO_REGISTRO_VACIO);
        return false;
    }

    public boolean VerificarMetodoGeneracion(String metodoGeneracion)
    {
        if(!metodoGeneracion.equals(""))
        {
            if(existeMetodoGeneracion(metodoGeneracion))
            {
                return true;
            }
            else
            {
                errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_METODO_GENERACION_NO_EXISTENTE);
                return false;
            }
        }
        errores.get(errores.size() - 1).AgregarError(ErrorRegistro.ERROR_METODO_GENERACION_VACIO);
        return false;
    }

    public boolean esNumericoEntero(String cadena)
    {
        try {
            Integer.parseInt(cadena);
            return true;
        } catch (NumberFormatException nfe){
            return false;
        }
    }

    public boolean esNumericoDecimal(String cadena)
    {
        try {
            Double.parseDouble(cadena);
            return true;
        } catch (NumberFormatException nfe){
            return false;
        }
    }

    public boolean esFecha(String fechaRegistro)
    {
        try {
            DateFormat formatoFecha;
            Date fecha ;
            formatoFecha = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            fecha = (Date)formatoFecha.parse(ReemplazarTexto(fechaRegistro,"/"," "));
            return true;
        }
        catch (ParseException e)
        {
            return false;
        }
    }

    public String ReemplazarTexto(String fechaRegistro, String marcdorAntiguo, String marcadorNuevo)
    {
        int posicion = fechaRegistro.indexOf(marcdorAntiguo);
        String nuevaFechaRegistro = fechaRegistro.substring(0, posicion) + marcadorNuevo + fechaRegistro.substring(posicion + 2,fechaRegistro.length());
        return nuevaFechaRegistro;
    }

    public boolean existePuntoMonitoreo(String puntoMonitoreo)
    {
        Hidcomponente hidcomponente = Hidcomponente.find("byCompnom",puntoMonitoreo).first();
        if(hidcomponente != null)
        {
            Hidpuntomonitoreo hidpuntomonitoreo = Hidpuntomonitoreo.find("byHidcomponente",hidcomponente).first();
            if(hidpuntomonitoreo != null)
            {
                return true;
            }
            return false;
        }
        return false;
    }

    public boolean existeTipoMedicion(String tipoMedicion)
    {
        Hidtipomedicion hidtipomedicion = Hidtipomedicion.find("byTipmednom",tipoMedicion).first();
        if(hidtipomedicion != null)
        {
            return true;
        }
        return false;
    }

    public boolean existeTipoRegistro(String tipoRegistro)
    {
        Hidtiporegistro hidtiporegistro = Hidtiporegistro.find("byTipregnom",tipoRegistro).first();
        if(hidtiporegistro != null)
        {
            return true;
        }
        return false;
    }

    public boolean existeMetodoGeneracion(String metodoGeneracion)
    {
        Hidmetodo hidmetodo = Hidmetodo.find("byMetnomb",metodoGeneracion).first();
        if(metodoGeneracion.equals("original"))
        {
            return true;
        }

        if(hidmetodo != null)
        {
            return true;
        }
        return false;
    }

    public Hidregistro CrearRegistro(String identificador, String fechaRegistro, String valorRegistro,
                                     String puntoMonitoreo, String tipoMedicion, String tipoRegistro, String metodoGeneracion)
    {
        Hidregistro hidregistro = new Hidregistro();

        //si no se ingresa el id, se toma como nuevo y se le asigna un id 0, de lo contrario se busca el registro
        //con dicho id , si no existiese se retorna valor nulo
        if(identificador.compareTo("") == 0)
        {
            hidregistro.setRegid(0);
        }
        else
        {
            hidregistro = Hidregistro.findById(Integer.valueOf(identificador));
            if(hidregistro == null)
            {
                return null;
            }
        }

        //se verifica que la fecha del registro este correctamente ingresada
        try {
            DateFormat formatoFecha = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date fecha = (Date)formatoFecha.parse(ReemplazarTexto(fechaRegistro,"/"," "));
            hidregistro.setRegfech(fecha);
        }
        catch (ParseException e)
        {
            return null;
        }

        //se ingresa el valor del registro
        hidregistro.setRegval(Double.valueOf(valorRegistro));

        //se busca el componente, punto de monitoreo, tipo de medicion, tipo de registro que coincidan con los nombres ingresados
        //en el archivo excel
        Hidcomponente hidcomponente = Hidcomponente.find("byCompnom",puntoMonitoreo).first();
        Hidpuntomonitoreo hidpuntomonitoreo = Hidpuntomonitoreo.find("byHidcomponente",hidcomponente).first();
        hidregistro.setHidpuntomonitoreo(hidpuntomonitoreo);

        Hidtipomedicion hidtipomedicion = Hidtipomedicion.find("byTipmednom",tipoMedicion).first();
        hidregistro.setHidtipomedicion(hidtipomedicion);

        Hidtiporegistro hidtiporegistro = Hidtiporegistro.find("byTipregnom",tipoRegistro).first();
        hidregistro.setHidtiporegistro(hidtiporegistro);

        //se verifica si el metodo de generacion de datos existe o si se trata de un dato original
        Hidmetodo hidmetodo = Hidmetodo.find("byMetnomb",metodoGeneracion).first();
        if(hidmetodo != null )
        {
            hidregistro.setRegtipmet(hidmetodo.getMetid());
        }
        else if (metodoGeneracion == "original")
        {
            hidregistro.setRegtipmet(0);
        }

        hidregistro.setRegfechmod(new Date());

        return hidregistro;
    }

    public void GuardarRegistros(List<Hidregistro> hidregistros)
    {
        for(int i = 0; i < hidregistros.size(); i++)
        {
            try{
                hidregistros.get(i).save();
            }
            catch (Exception e)
            {
                ErrorRegistro errorRegistro = new ErrorRegistro(i + 1);
                errorRegistro.AgregarError(ErrorRegistro.ERROR_DUPLICIDAD_REGISTRO);
                errorRegistro.ImprmirErrores();
                errores.add(errorRegistro);
            }
        }
    }
}
